package com.petter.lock.juc.semaphore;

import java.util.concurrent.Semaphore;

/**
 *
 * 链接：https://www.pdai.tech/md/java/thread/java-thread-x-juc-tool-semaphore.html
 *
 * 单独使用Semaphore是不会使用到AQS的条件队列的 不同于CyclicBarrier和ReentrantLock，单独使用Semaphore是不会使用到AQS的条件队列的，
 * 其实，只有进行await操作才会进入条件队列，其他的都是在同步队列中，只是当前线程会被park。
 * ¶ 场景问题 ¶
 * semaphore初始化有10个令牌，11个线程同时各调用1次acquire方法，会发生什么?
 * 答案：拿不到令牌的线程阻塞，不会继续往下运行。
 *
 * ¶ semaphore初始化有10个令牌，一个线程重复调用11次acquire方法，会发生什么?
 * 答案：线程阻塞，不会继续往下运行。可能你会考虑类似于锁的重入的问题，很好，但是，令牌没有重入的概念。你只要调用一次acquire方法，就需要有一个令牌才能继续运行。
 * ¶ semaphore初始化有1个令牌，1个线程调用一次acquire方法，然后调用两次release方法，之后另外一个线程调用acquire(2)方法，此线程能够获取到足够的令牌并继续运行吗?
 * 答案：能，原因是release方法会添加令牌，并不会以初始化的大小为准。
 * ¶ semaphore初始化有2个令牌，一个线程调用1次release方法，然后一次性获取3个令牌，会获取到吗?
 * 答案：能，原因是release会添加令牌，并不会以初始化的大小为准。Semaphore中release方法的调用并没有限制要在acquire后调用。
 *
 *
 * 重点： release会添加令牌，并不会以初始化的大小为准。Semaphore中release方法的调用并没有限制要在acquire后调用。
 *
 *
 *
 *
 * @author : GD
 * @date :2021/12/20 : 22:23
 */
public class SemaphoreTest1 {
    public final static int SEM_SIZE = 7;

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(SEM_SIZE);
        MyThread t1 = new MyThread("t1", semaphore);
        MyThread t2 = new MyThread("t2", semaphore);
        t1.start();
        t2.start();
        int permits = 5;
        System.out.println(Thread.currentThread().getName() + " trying to acquire");
        try {
            semaphore.acquire(permits);
            System.out.println(Thread.currentThread().getName() + " acquire successfully");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
            System.out.println(Thread.currentThread().getName() + " release successfully");
        }
    }
}




class MyThread extends Thread {
    private Semaphore semaphore;

    public MyThread(String name, Semaphore semaphore) {
        super(name);
        this.semaphore = semaphore;
    }
    @Override
    public void run() {
        int count = 3;
        System.out.println(Thread.currentThread().getName() + " trying to acquire");
        try {
            Thread.sleep(1000);
            semaphore.acquire(count);
            System.out.println(Thread.currentThread().getName() + " acquire successfully");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release(count);
            System.out.println(Thread.currentThread().getName() + " release successfully");
        }
    }
}
